import axios from 'axios'
import { ElMessageBox, ElMessage } from 'element-plus'
import md5 from 'crypto-js/md5'
import qs from 'qs'
import store from '@/store'
import {getToken, getSiteInfo, getRefreshToken} from '@/utils/storage'
import { encrypt } from "@/utils/cryptoAes";
import { getRandomString } from '@/utils/tools'
const service = axios.create({
    baseURL: process.env.VUE_APP_SERVICE_BASE,
    timeout: 30000
})
const getHeader = (refreshToken) => {
    let timestamp = new Date().valueOf()
    let token = store.getters.token ? store.getters.token : getToken() 
    if(refreshToken) token = getRefreshToken()
    let uuid = store.getters.siteInfo ? getSiteInfo().uuid : null
    let nonce = getRandomString(16)
    let header = {
        'X-nonce': nonce,
        'X-timestamp': timestamp
    }
    if(token) header["X-token"] = token
    if(uuid) header["X-uuid"] = uuid
    header['X-sign'] = encrypt(md5(qs.stringify(header, {encode: false})).toString())
    return header
}
// 请求拦截器
service.interceptors.request.use(
    config => {
        let header = getHeader()
        config.headers = Object.assign({},config.headers,header)
        if (config.method === 'post'){
            if(config.data && config.data.file && config.data.file instanceof File){
                config.headers['Content-Type'] = 'multipart/form-data'
                let formData = new FormData()
                for(let i in config.data){
                    formData.append(i, config.data[i])
                }
                config.data = formData
            }else{
                config.headers['Content-Type'] = 'application/json'
            }
        }
        return config
    },
    error => {
        if(process.env.NODE_ENV === 'development') console.log(error)
        return Promise.reject(error)
    }
)
// 响应拦截器
// 是否正在刷新的标记
let isRefreshing = false
//重试队列
let requests = []
service.interceptors.response.use(
    response => {
        const config = response.config
        const res = response.data
        if(res instanceof Blob){
            return res
        } else if (res.code !== 20000) {
            ElMessage({
                showClose: true,
                message: res.message || 'Error',
                type: 'error',
                duration: 5 * 1000
            })

            // 根据后端返回码，需要重新登录的情况
            if (res.code === 50008) {
                // to refreshing token
                if(process.env.NODE_ENV === 'development') console.log(response)
                if(!isRefreshing){
                    isRefreshing = true
                    //更换token进行请求
                    if(store.state.user.refresh_token){
                        store.commit('user/SET_TOKEN',{token: store.state.user.refresh_token})
                    }
                    return store.dispatch('user/resetToken').then(() => {
                        let header = getHeader()
                        config.headers = Object.assign({},config.headers,header)
                        requests.forEach(cb => cb(config))
                        return service(config)
                    }).catch(() => {
                        ElMessageBox.confirm('<p><i class="iconfont" style="color: #FF9700;margin-right: 5px;">&#xe60e;</i>登录过期，可以留在此页面或者重新登录</p>', '确认退出', {
                            confirmButtonText: '重新登录',
                            cancelButtonText: '取消',
                            dangerouslyUseHTMLString: true
                        }).then(() => {
                            store.commit('user/RESET_STATE')
                            store.commit('user/REMOVE_TOKEN')
                            location.reload()
                        })
                    }).finally(() => {
                        isRefreshing = false
                    })
                } else {
                    if(response.request.responseURL.indexOf('auth/refreshToken') !== -1) return Promise.reject(new Error(res.message || 'Error'))
                    return new Promise(resolve => {
                        requests.push((config) => {
                            resolve(service(config))
                        })
                    })
                }
            }else{
                return Promise.reject(new Error(res.message || 'Error'))
            }
        } else {
            return res
        }
    },
    error => {
        if(process.env.NODE_ENV === 'development') console.log('err' + error) // for debug
        ElMessage({
            showClose: true,
            message: error.message,
            type: 'error',
            duration: 5 * 1000
        })
        return Promise.reject(error)
    }
)

export default service
